from PyQt6.QtWidgets import (QWidget, QVBoxLayout, QHBoxLayout, QLabel, 
                           QScrollArea, QGridLayout, QFrame, QApplication,
                           QPushButton, QFileDialog, QMessageBox)
from PyQt6.QtCore import Qt, pyqtSignal
import json
from pathlib import Path
import time
from .book_card import BookCard  # 导入 BookCard 类
from .flow_layout import FlowLayout  # 修改这里，从本地导入 FlowLayout
import re
from utils.logger import Logger, log_function_call
import os

logger = Logger.get_logger()

class BookshelfWidget(QWidget):
    bookSelected = pyqtSignal(str)
    addBookRequested = pyqtSignal()  # 添加信号

    def __init__(self, parent=None):
        super().__init__(parent)
        self.books = []
        self.cards = {}
        self.current_layout = {}
        
        self.init_ui()

    def init_ui(self):
        # 创建主布局
        self.main_layout = QVBoxLayout(self)
        self.main_layout.setContentsMargins(16, 16, 16, 16)  # 设置外边距
        self.main_layout.setSpacing(16)
        
        # 添加顶部工具栏
        toolbar = QWidget()
        toolbar_layout = QHBoxLayout(toolbar)
        toolbar_layout.setContentsMargins(0, 0, 0, 10)
        
        # 添加书籍按钮
        add_btn = QPushButton("添加书籍")
        add_btn.setObjectName("addBookBtn")
        add_btn.clicked.connect(self.add_book_clicked)
        add_btn.setStyleSheet("""
            QPushButton#addBookBtn {
                background: rgba(255, 255, 255, 0.1);
                border: none;
                border-radius: 4px;
                color: white;
                padding: 6px 12px;
                font-size: 13px;
            }
            QPushButton#addBookBtn:hover {
                background: rgba(255, 255, 255, 0.15);
            }
        """)
        toolbar_layout.addWidget(add_btn)
        toolbar_layout.addStretch()
        
        self.main_layout.addWidget(toolbar)
        
        # 创建滚动区域
        scroll = QScrollArea()
        scroll.setWidgetResizable(True)
        scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
        scroll.setStyleSheet("""
            QScrollArea {
                border: none;
                background: transparent;
            }
            QScrollBar:vertical {
                width: 8px;
                background: transparent;
            }
            QScrollBar::handle:vertical {
                background: rgba(255, 255, 255, 0.1);
                border-radius: 4px;
            }
            QScrollBar::handle:vertical:hover {
                background: rgba(255, 255, 255, 0.2);
            }
        """)
        
        # 创建书架容器
        self.shelf_container = QWidget()
        self.flow_layout = FlowLayout(self.shelf_container)  # 使用流式布局
        self.flow_layout.setSpacing(16)  # 设置间距
        self.flow_layout.setContentsMargins(0, 0, 0, 0)
        
        scroll.setWidget(self.shelf_container)
        self.main_layout.addWidget(scroll)

    def create_book_card(self, book):
        """创建书籍卡片"""
        try:
            # 使用更安全的编码处理方式
            title = book.get('title', 'Unknown')
            try:
                title.encode('utf-8').decode('utf-8')
            except UnicodeError:
                title = title.encode('utf-8', errors='ignore').decode('utf-8')
            
            card = BookCard(book)
            card.bookSelected.connect(lambda bid=book['id']: self.bookSelected.emit(bid))
            card.deleteRequested.connect(self.delete_book)
            logger.debug(f"创建卡片成功: {title}")
            return card
        except Exception as e:
            logger.error(f"创建卡片失败: {book.get('title', 'Unknown')}")
            logger.debug(f"错误详情: {str(e)}")
            return None

    def load_books(self):
        """加载书架数据"""
        try:
            logger.info("开始加载书架数据")
            bookshelf_path = Path("data/bookshelf.json")
            
            # 确保数据目录存在
            bookshelf_path.parent.mkdir(parents=True, exist_ok=True)
            
            if bookshelf_path.exists():
                with open(bookshelf_path, 'r', encoding='utf-8') as f:
                    data = json.load(f)
                    self.books = data.get('books', [])
                    logger.debug(f"成功加载 {len(self.books)} 本书")
                    
                    # 确保所有必要的字段都存在
                    for book in self.books:
                        if 'last_read_time' not in book:
                            book['last_read_time'] = int(time.time())
                        if 'last_operation' not in book:
                            book['last_operation'] = "导入书籍"
            else:
                self.books = []
                # 创建空的书架文件
                with open(bookshelf_path, 'w', encoding='utf-8') as f:
                    json.dump({"books": [], "display_settings": {"card_size": 150}}, f, indent=2)
                logger.debug("创建新的空书架文件")
            
            # 先排序
            self.sort_books()
            
            # 再刷新显示
            QApplication.processEvents()  # 处理待处理的事件
            self.refresh_bookshelf()
            logger.info("书架加载完成")
            
        except Exception as e:
            error_msg = f"加载书架数据失败: {str(e)}\n{traceback.format_exc()}"
            logger.error(error_msg)
            QMessageBox.warning(self, "错误", f"加载书架失败: {str(e)}")
            self.books = []
            self.refresh_bookshelf()

    def sort_books(self):
        """排序书籍"""
        try:
            # 确保所有时间戳都是整数
            for book in self.books:
                if isinstance(book.get('last_read_time'), str):
                    book['last_read_time'] = int(book['last_read_time'])
                elif not book.get('last_read_time'):
                    book['last_read_time'] = int(time.time())
            
            # 按时间戳排序（从大到小）
            self.books.sort(
                key=lambda x: (
                    -int(x.get('last_read_time', 0)),  # 最后阅读时间倒序
                    -int(x.get('id', '0'))  # ID倒序作为次要排序
                )
            )
            logger.debug("书籍排序完成")
        except Exception as e:
            logger.error(f"书籍排序失败: {str(e)}")

    @log_function_call
    def save_books(self):
        """保存书架数据"""
        try:
            logger.info("开始保存书架数据")
            bookshelf_path = Path("data/bookshelf.json")
            
            # 确保目录存在
            bookshelf_path.parent.mkdir(parents=True, exist_ok=True)
            
            # 读取现有数据（如果存在）
            if bookshelf_path.exists():
                with open(bookshelf_path, 'r', encoding='utf-8') as f:
                    data = json.load(f)
                logger.debug(f"读取现有书架数据: {len(data.get('books', []))} 本书")
            else:
                data = {"books": [], "display_settings": {"card_size": 150}}
                logger.debug("创建新的书架数据文件")
            
            # 更新书籍列表
            data['books'] = self.books
            
            # 保存数据
            with open(bookshelf_path, 'w', encoding='utf-8') as f:
                json.dump(data, f, ensure_ascii=False, indent=2)
            
            logger.info(f"书架数据保存成功，共 {len(self.books)} 本书")
            return True
            
        except Exception as e:
            error_msg = f"保存书架数据失败: {str(e)}\n{traceback.format_exc()}"
            logger.error(error_msg)
            QMessageBox.warning(self, "错误", f"保存书架失败: {str(e)}")
            return False

    def refresh_bookshelf(self):
        """刷新书架显示"""
        try:
            logger.info("开始刷新书架显示")
            
            # 清除所有现有卡片
            self.clear_layout()
            
            # 检查是否有书籍
            if not self.books:
                logger.debug("书架为空")
                return
            
            # 重新创建卡片
            for book in self.books:
                try:
                    card = self.create_book_card(book)
                    if card:
                        self.flow_layout.addWidget(card)
                except Exception as e:
                    logger.error(f"添加卡片失败: {book.get('title', 'Unknown')}")
                    continue

            # 强制更新布局
            self.flow_layout.update()
            self.shelf_container.update()
            self.update()
            QApplication.processEvents()
            
            logger.info(f"书架刷新完成，共 {len(self.books)} 本书")
            
        except Exception as e:
            logger.error(f"刷新书架失败: {str(e)}")
            QMessageBox.warning(self, "错误", "刷新书架失败")

    @log_function_call
    def add_new_book(self, book_info):
        """添加新书并排序"""
        try:
            # 只记录基本信息
            log_info = {
                'title': book_info.get('title'),
                'id': book_info.get('id')
            }
            logger.info(f"开始添加新书: {log_info['title']}")
            
            # 检查文件是否存在
            if 'path' in book_info:
                file_path = Path(book_info['path'])
                if not file_path.exists():
                    error_msg = f"文件不存在: {file_path}"
                    logger.error(error_msg)
                    QMessageBox.warning(self, "错误", error_msg)
                    return False
                
                # 检查文件是否可读
                try:
                    with open(file_path, 'r', encoding='utf-8') as f:
                        f.read(1024)  # 尝试读取一小部分
                except Exception as e:
                    error_msg = f"文件无法读取: {str(e)}"
                    logger.error(error_msg)
                    QMessageBox.warning(self, "错误", error_msg)
                    return False
            
            # 检查是否已存在相同书籍
            existing_book = next(
                (book for book in self.books 
                 if book['title'] == book_info['title'] and 
                 book['path'] == book_info['path']), 
                None
            )
            
            if existing_book:
                logger.info(f"发现重复书籍: {book_info['title']}")
                # 显示提示对话框
                reply = QMessageBox.question(
                    self,
                    "添加书籍",
                    f"书籍《{book_info['title']}》已存在，是否覆盖？",
                    QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No,
                    QMessageBox.StandardButton.No
                )
                
                if reply == QMessageBox.StandardButton.Yes:
                    # 更新已存在的书籍
                    current_time = int(time.time())
                    book_info['last_read_time'] = current_time
                    book_info['last_operation'] = "更新书籍"
                    book_info['add_time'] = time.strftime('%Y-%m-%d %H:%M:%S')
                    
                    # 更新书籍信息
                    existing_book.update(book_info)
                    logger.info(f"更新已存在的书籍: {book_info['title']}")
                else:
                    logger.info(f"取消添加重复书籍: {book_info['title']}")
                    return False
            else:
                # 添加新书
                current_time = int(time.time())
                book_info['last_read_time'] = current_time
                book_info['last_operation'] = "新增书籍"
                book_info['add_time'] = time.strftime('%Y-%m-%d %H:%M:%S')
                
                # 添加新书到列表开头
                self.books.insert(0, book_info)
                logger.info(f"添加新书成功: {book_info['title']}")
            
            # 保存并刷新
            success = self.save_books()
            if success:
                # 强制重新加载和刷新
                self.load_books()
                logger.info(f"书籍 {book_info['title']} 添加成功")
                return True
            return False
            
        except Exception as e:
            error_msg = f"添加新书失败: {str(e)}\n{traceback.format_exc()}"
            logger.error(error_msg)
            QMessageBox.warning(self, "错误", f"添加书籍失败: {str(e)}")
            return False

    def sort_and_refresh(self):
        """排序并刷新显示"""
        try:
            print("\n开始排序书籍...")
            print("排序前:", [(b['title'], b.get('last_read_time', 0)) for b in self.books])
            
            # 确保所有时间戳都是整数
            for book in self.books:
                if isinstance(book.get('last_read_time'), str):
                    book['last_read_time'] = int(book['last_read_time'])
                elif not book.get('last_read_time'):
                    book['last_read_time'] = int(time.time())
            
            # 按时间戳排序（从大到小）
            self.books.sort(
                key=lambda x: (
                    -int(x.get('last_read_time', 0)),  # 最后阅读时间倒序
                    -int(x.get('id', '0'))  # ID倒序作为次要排序
                )
            )
            
            # 保存排序后的结果
            self.save_books()
            
            print("排序后:", [(b['title'], b.get('last_read_time', 0)) for b in self.books])
            
            # 智能刷新显示
            self.refresh_bookshelf()
            
            print("排序和刷新完成\n")
            
        except Exception as e:
            print(f"排序书籍失败: {str(e)}")
            print("当前书籍数据:", self.books)

    def update_book_time(self, book_id, new_time, operation="打开阅读"):
        """更新书籍时间和操作信息"""
        try:
            # 更新时间和操作信息
            for book in self.books:
                if book['id'] == book_id:
                    book['last_read_time'] = new_time
                    book['last_operation'] = operation
                    print(f"更新书籍: {book['title']} -> {new_time} ({operation})")
                    break
            
            # 保存更改
            self.save_books()
            
            # 重新排序
            self.books.sort(
                key=lambda x: (
                    -int(x.get('last_read_time', 0)),  # 最后操作时间倒序
                    -int(x.get('id', '0'))  # ID倒序作为次要排序
                )
            )
            
            # 立即刷新显示
            self.refresh_bookshelf()
            
        except Exception as e:
            print(f"更新书籍时间失败: {str(e)}")

    def clear_layout(self):
        """清除所有卡片"""
        try:
            logger.debug("开始清除布局")
            while self.flow_layout.count():
                item = self.flow_layout.takeAt(0)
                if item.widget():
                    item.widget().deleteLater()
            self.flow_layout.update()
            logger.debug("布局清除完成")
        except Exception as e:
            logger.error(f"清除布局失败: {str(e)}")

    def delete_book(self, book_id):
        """删除书籍"""
        try:
            # 找到要删除的书籍
            book = next((b for b in self.books if b['id'] == book_id), None)
            if book:
                # 从列表中移除
                self.books.remove(book)
                # 保存更改
                self.save_books()
                # 刷新显示
                self.refresh_bookshelf()
                print(f"删除书籍成功: {book['title']}")
        except Exception as e:
            print(f"删除书籍失败: {str(e)}")

    def add_book_clicked(self):
        """处理添加书籍按钮点击"""
        try:
            # 打开文件选择对话框
            file_name, _ = QFileDialog.getOpenFileName(
                self,
                "选择TXT文件",
                "",
                "文本文件 (*.txt)"
            )
            
            if file_name:
                # 获取文件信息
                file_path = Path(file_name)
                title = file_path.stem  # 使用文件名作为书名
                
                # 读取文件内容并解析章节
                with open(file_path, 'r', encoding='utf-8') as f:
                    content = f.read()
                
                # 解析章节
                chapters = self.parse_chapters(content)
                
                # 创建新书信息
                book_info = {
                    'title': title,
                    'path': str(file_path),
                    'cover': '',  # 默认无封面
                    'progress': 0,  # 初始进度为0
                    'last_position': 0,  # 初始阅读位置
                    'current_chapter': 0,  # 当前章节索引
                    'chapters': chapters,  # 添加章节信息
                    'id': str(int(time.time())),  # 使用时间戳作为ID
                    'add_time': time.strftime('%Y-%m-%d %H:%M:%S')
                }
                
                # 添加新书到书架
                if self.add_new_book(book_info):
                    print(f"成功添加书籍: {title}")
                else:
                    print(f"添加书籍失败: {title}")
        
        except Exception as e:
            print(f"添加书籍失败: {str(e)}")

    def parse_chapters(self, content):
        """解析章节内容"""
        try:
            chapters = []
            current_chapter = None
            current_content = []
            
            # 修改章节标题匹配模式，使其更严格
            chapter_patterns = [
                # 标准章节格式
                r'^第[0-9零一二三四五六七八九十百千万]+[章节回集卷部篇][\s\t]*[：:]*[\s\t]*\S+',
                # 数字编号格式
                r'^[0-9]+[\s\t]*[、.．][\s\t]*第.+[章节].*$',
                # 特殊章节
                r'^(序章|楔子|序言|前言|引子|尾声|终章|后记|番外).*$',
                # 英文章节
                r'^Chapter\s*[0-9]+.*$',
                # 卷/部/篇
                r'^第[0-9零一二三四五六七八九十百千万]+[卷部篇].*$',
            ]
            
            def is_chapter_title(line):
                line = line.strip()
                if not line:
                    return False
                
                # 1. 长度检查 - 章节标题通常不会太长
                if len(line) > 50:
                    return False
                
                # 2. 特殊字符检查 - 章节标题通常不会包含特殊符号
                if any(char in line for char in ['【', '】', '《', '》', '［', '］', '〖', '〗']):
                    return False
                
                # 3. 数字比例检查 - 章节标题中的数字不会太多
                digit_count = sum(1 for c in line if c.isdigit())
                if digit_count > len(line) * 0.5:
                    return False
                
                # 4. 模式匹配
                return any(re.match(pattern, line) for pattern in chapter_patterns)
            
            lines = content.split('\n')
            seen_chapters = {}  # 用于记录已见过的章节标题
            
            for line in lines:
                line = line.strip()
                if not line:
                    continue
                
                if is_chapter_title(line):
                    # 保存前一章节
                    if current_chapter is not None:
                        chapter_content = '\n'.join(current_content)
                        if len(chapter_content.strip()) > 0:  # 只添加有内容的章节
                            if current_chapter not in seen_chapters:
                                chapters.append({
                                    'title': current_chapter,
                                    'content': chapter_content
                                })
                                seen_chapters[current_chapter] = True
                    
                    # 开始新章节
                    current_chapter = line
                    current_content = []
                else:
                    if current_chapter is not None:
                        current_content.append(line)
                    else:
                        # 处理开头没有章节标题的情况
                        current_chapter = "开始"
                        current_content = [line]
            
            # 保存最后一章
            if current_chapter and current_content:
                chapter_content = '\n'.join(current_content)
                if len(chapter_content.strip()) > 0:  # 只添加有内容的章节
                    if current_chapter not in seen_chapters:
                        chapters.append({
                            'title': current_chapter,
                            'content': chapter_content
                        })
            
            # 如果没有识别出任何章节，将整个内容作为一章
            if not chapters:
                chapters = [{
                    'title': '正文',
                    'content': content
                }]
            
            print(f"解析完成: 共{len(chapters)}章")
            return chapters
            
        except Exception as e:
            print(f"解析章节失败: {str(e)}")
            return [{
                'title': '解析失败',
                'content': content
            }]

    def update_book_progress(self, book_info):
        """更新书籍进度"""
        try:
            # 查找并更新书籍信息
            for book in self.books:
                if book['id'] == book_info['id']:
                    # 更新阅读进度相关信息
                    book['current_chapter'] = book_info.get('current_chapter', 0)
                    book['last_position'] = book_info.get('last_position', 0.0)
                    book['last_read_time'] = book_info.get('last_read_time', int(time.time()))
                    
                    # 保存到文件
                    self.save_books()
                    break
                    
        except Exception as e:
            print(f"更新书籍进度失败: {str(e)}") 